package sdk.org.apache.shiro.G2_使用.C06_授权.代码授权;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;

public class Main {

    public static void main(String[] args) {
        try {
            run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private static void run() throws Exception {
        // 1、获取SecurityManager工厂，此处使用Ini配置文件初始化SecurityManager
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:sdk/org/apache/shiro/G2_使用/C06_授权/代码授权/ini/shiro-authorizer.ini");
        
        //2、得到SecurityManager实例并绑定给SecurityUtils
        SecurityManager securityManager = factory.getInstance();
        //   这是一个全局设置，设置一次即可
        SecurityUtils.setSecurityManager(securityManager);

        //3、得到Subject及创建用户名/密码身份验证Token（即用户身份/凭证）
        //   通过SecurityUtils得到Subject，其会自动绑定到当前线程；如果在web环境在请求结束时需要解除绑定；然后获取身份验证的Token，如用户名/密码；
        Subject currentUser = SecurityUtils.getSubject();
        if ( !currentUser.isAuthenticated() ) {
            UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
            token.setRememberMe(true);
            try {
                // 4、登录，即身份验证
                //    调用subject.login方法进行登录，其会自动委托给SecurityManager.login方法进行登录；
                currentUser.login(token);
            } catch (UnknownAccountException uae) {  // 错误的帐号
                System.out.println("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ex) {  // 错误的凭证
                System.out.println("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (ExpiredCredentialsException ex) {  // 过期的凭证
                System.out.println("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException ex) {  // 禁用的帐号
                System.out.println("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            } catch (DisabledAccountException ex) {  // 锁定的帐号
                System.out.println("The account for username " + token.getPrincipal() + " is disabled.  " +
                        "Please contact your administrator to enabled it.");
            } catch (ExcessiveAttemptsException ex) {  // 登录失败次数过多
                System.out.println("The account for username " + token.getPrincipal() + " is disabled.");
            } catch (AuthenticationException ae) {
                // ... catch more exceptions here (maybe custom ones specific to your application?
                //unexpected condition?  error?
                // 5、身份验证失败
                ae.printStackTrace();
            }
        }
        
        // 断言用户已经登录
        System.out.println("当前用户"+currentUser.getPrincipal()+"的登录状态："+currentUser.isAuthenticated());
        // 判断拥有权限：user:create
        System.out.println("判断用户是否拥有[user1:update]权限："+currentUser.isPermitted("user1:update"));
        System.out.println("判断用户是否拥有[user2:update]权限："+currentUser.isPermitted("user2:update"));
        // 通过二进制位的方式表示权限
        System.out.println("判断用户通过二进制位的方式是否拥有[+user1+2]权限："+currentUser.isPermitted("+user1+2"));//新增权限
        System.out.println("判断用户通过二进制位的方式是否拥有[+user1+8]权限："+currentUser.isPermitted("+user1+8"));//查看权限
        System.out.println("判断用户通过二进制位的方式是否拥有[+user2+10]权限："+currentUser.isPermitted("+user2+10"));//新增及查看
        System.out.println("判断用户通过二进制位的方式是否拥有[+user1+4]权限："+currentUser.isPermitted("+user1+4"));//没有删除权限
        System.out.println("判断用户通过二进制位的方式是否拥有[menu:view]权限："+currentUser.isPermitted("menu:view"));//通过MyRolePermissionResolver解析得到的权限
        
        // 6、退出
        // 其会自动委托给SecurityManager.logout方法退出。
        currentUser.logout();        
    }
}
